﻿using CoreWCF;
using SD.Infrastructure.DTOBase;
using SlamDunk.MES.AppService.Maps;
using SlamDunk.MES.Domain.Entities.FoundationContext;
using SlamDunk.MES.Domain.Entities.MaintenanceContext;
using SlamDunk.MES.Domain.IRepositories;
using SlamDunk.MES.Domain.Mediators;
using SlamDunk.MES.IAppService.DTOs.Outputs.FoundationContext;
using SlamDunk.MES.IAppService.DTOs.Outputs.MaintenanceContext;
using SlamDunk.MES.IAppService.DTOs.Outputs.ResourceContext;
using SlamDunk.MES.IAppService.Interfaces;
using SlamDunk.ValueObjects.Enums;
using System;
using System.Collections.Generic;
using System.Linq;

namespace SlamDunk.MES.AppService.Implements
{
    /// <summary>
    /// 维护管理服务契约实现
    /// </summary>
    [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall, IncludeExceptionDetailInFaults = true)]
    public class MaintenanceContract : IMaintenanceContract
    {
        #region # 字段及构造器

        /// <summary>
        /// 仓储中介者
        /// </summary>
        private readonly RepositoryMediator _repMediator;

        /// <summary>
        /// 单元事务
        /// </summary>
        private readonly IUnitOfWorkMES _unitOfWork;

        /// <summary>
        /// 依赖注入构造器
        /// </summary>
        public MaintenanceContract(RepositoryMediator repMediator, IUnitOfWorkMES unitOfWork)
        {
            this._repMediator = repMediator;
            this._unitOfWork = unitOfWork;
        }

        #endregion


        //命令部分

        #region # 创建设备资产 —— void CreateEquipmentAsset(string assetNo, string assetName...
        /// <summary>
        /// 创建设备资产
        /// </summary>
        /// <param name="assetNo">设备资产编号</param>
        /// <param name="assetName">设备资产名称</param>
        /// <param name="equipmentId">设备Id</param>
        /// <param name="producedDate">生产日期</param>
        /// <param name="purchasedDate">采购日期</param>
        /// <param name="enabledDate">启用日期</param>
        /// <param name="manufacturer">制造商</param>
        /// <param name="specification">规格</param>
        /// <param name="modelNo">型号</param>
        /// <param name="worth">价值</param>
        /// <param name="serviceLife">使用年限</param>
        /// <param name="depreciableLife">折旧年限</param>
        /// <param name="supportPhone">售后电话</param>
        /// <param name="facilityId">工厂模型Id</param>
        /// <param name="principal">负责人</param>
        /// <param name="description">描述</param>
        public void CreateEquipmentAsset(string assetNo, string assetName, Guid equipmentId, DateTime producedDate, DateTime purchasedDate, DateTime? enabledDate, string manufacturer, string specification, string modelNo, decimal worth, string serviceLife, string depreciableLife, string supportPhone, Guid? facilityId, string principal, string description)
        {
            EquipmentAsset equipmentAsset = new EquipmentAsset(assetNo, assetName, equipmentId, producedDate, purchasedDate, enabledDate, manufacturer, specification, modelNo, worth, serviceLife, depreciableLife, supportPhone, facilityId, principal, description);

            this._unitOfWork.RegisterAdd(equipmentAsset);
            this._unitOfWork.Commit();
        }
        #endregion

        #region # 修改设备资产 —— void UpdateEquipmentAsset(Guid equipmentAssetId, string assetNo...
        /// <summary>
        /// 修改设备资产
        /// </summary>
        /// <param name="equipmentAssetId">设备资产Id</param>
        /// <param name="assetNo">设备资产编号</param>
        /// <param name="assetName">设备资产名称</param>
        /// <param name="producedDate">生产日期</param>
        /// <param name="purchasedDate">采购日期</param>
        /// <param name="enabledDate">启用日期</param>
        /// <param name="manufacturer">制造商</param>
        /// <param name="specification">规格</param>
        /// <param name="modelNo">型号</param>
        /// <param name="worth">价值</param>
        /// <param name="serviceLife">使用年限</param>
        /// <param name="depreciableLife">折旧年限</param>
        /// <param name="supportPhone">售后电话</param>
        /// <param name="facilityId">工厂模型Id</param>
        /// <param name="principal">负责人</param>
        /// <param name="description">描述</param>
        public void UpdateEquipmentAsset(Guid equipmentAssetId, string assetNo, string assetName, DateTime producedDate, DateTime purchasedDate, DateTime? enabledDate, string manufacturer, string specification, string modelNo, decimal worth, string serviceLife, string depreciableLife, string supportPhone, Guid? facilityId, string principal, string description)
        {
            EquipmentAsset equipmentAsset = this._unitOfWork.Resolve<EquipmentAsset>(equipmentAssetId);
            equipmentAsset.UpdateInfo(assetNo, assetName, producedDate, purchasedDate, enabledDate, manufacturer, specification, modelNo, worth, serviceLife, depreciableLife, supportPhone, facilityId, principal, description);

            this._unitOfWork.RegisterSave(equipmentAsset);
            this._unitOfWork.Commit();
        }
        #endregion

        #region # 删除设备资产 —— void RemoveEquipmentAsset(Guid equipmentAssetId)
        /// <summary>
        /// 删除设备资产
        /// </summary>
        /// <param name="equipmentAssetId">设备资产Id</param>
        public void RemoveEquipmentAsset(Guid equipmentAssetId)
        {
            this._unitOfWork.RegisterRemove<EquipmentAsset>(equipmentAssetId);
            this._unitOfWork.Commit();
        }
        #endregion

        #region # 正常设备资产 —— void NormalizeEquipmentAsset(Guid equipmentAssetId)
        /// <summary>
        /// 正常设备资产
        /// </summary>
        /// <param name="equipmentAssetId">设备资产Id</param>
        public void NormalizeEquipmentAsset(Guid equipmentAssetId)
        {
            EquipmentAsset equipmentAsset = this._unitOfWork.Resolve<EquipmentAsset>(equipmentAssetId);
            equipmentAsset.Normalize();

            this._unitOfWork.RegisterSave(equipmentAsset);
            this._unitOfWork.Commit();
        }
        #endregion

        #region # 故障设备资产 —— void FailEquipmentAsset(Guid equipmentAssetId)
        /// <summary>
        /// 故障设备资产
        /// </summary>
        /// <param name="equipmentAssetId">设备资产Id</param>
        public void FailEquipmentAsset(Guid equipmentAssetId)
        {
            EquipmentAsset equipmentAsset = this._unitOfWork.Resolve<EquipmentAsset>(equipmentAssetId);
            equipmentAsset.Fail();

            this._unitOfWork.RegisterSave(equipmentAsset);
            this._unitOfWork.Commit();
        }
        #endregion

        #region # 维护设备资产 —— void MaintainEquipmentAsset(Guid equipmentAssetId)
        /// <summary>
        /// 维护设备资产
        /// </summary>
        /// <param name="equipmentAssetId">设备资产Id</param>
        public void MaintainEquipmentAsset(Guid equipmentAssetId)
        {
            EquipmentAsset equipmentAsset = this._unitOfWork.Resolve<EquipmentAsset>(equipmentAssetId);
            equipmentAsset.Maintain();

            this._unitOfWork.RegisterSave(equipmentAsset);
            this._unitOfWork.Commit();
        }
        #endregion

        #region # 报废设备资产 —— void ScrapEquipmentAsset(Guid equipmentAssetId)
        /// <summary>
        /// 报废设备资产
        /// </summary>
        /// <param name="equipmentAssetId">设备资产Id</param>
        public void ScrapEquipmentAsset(Guid equipmentAssetId)
        {
            EquipmentAsset equipmentAsset = this._unitOfWork.Resolve<EquipmentAsset>(equipmentAssetId);
            equipmentAsset.Scrap();

            this._unitOfWork.RegisterSave(equipmentAsset);
            this._unitOfWork.Commit();
        }
        #endregion

        #region # 创建设备维护类 —— void CreateEquipmentMaintainClass(string classNo, string className...
        /// <summary>
        /// 创建设备维护类
        /// </summary>
        /// <param name="classNo">维护类编号</param>
        /// <param name="className">维护类名称</param>
        /// <param name="maintainedContent">维护内容</param>
        /// <param name="maintainedInterval">维护周期</param>
        /// <param name="maintainedPrincipal">维护负责人</param>
        /// <param name="facilityId">工厂模型Id</param>
        /// <param name="description">描述</param>
        public void CreateEquipmentMaintainClass(string classNo, string className, string maintainedContent, string maintainedInterval, string maintainedPrincipal, Guid? facilityId, string description)
        {
            EquipmentMaintainClass maintainClass = new EquipmentMaintainClass(classNo, className, maintainedContent, maintainedInterval, maintainedPrincipal, facilityId, description);

            this._unitOfWork.RegisterAdd(maintainClass);
            this._unitOfWork.Commit();
        }
        #endregion

        #region # 修改设备维护类 —— void UpdateEquipmentMaintanClass(Guid equipmentMaintainClassId...
        /// <summary>
        /// 修改设备维护类
        /// </summary>
        /// <param name="equipmentMaintainClassId">设备维护类Id</param>
        /// <param name="classNo">维护类编号</param>
        /// <param name="className">维护类名称</param>
        /// <param name="maintainedContent">维护内容</param>
        /// <param name="maintainedInterval">维护周期</param>
        /// <param name="maintainedPrincipal">维护负责人</param>
        /// <param name="facilityId">工厂模型Id</param>
        /// <param name="description">描述</param>
        public void UpdateEquipmentMaintanClass(Guid equipmentMaintainClassId, string classNo, string className, string maintainedContent, string maintainedInterval, string maintainedPrincipal, Guid? facilityId, string description)
        {
            EquipmentMaintainClass maintainClass = this._unitOfWork.Resolve<EquipmentMaintainClass>(equipmentMaintainClassId);
            maintainClass.UpdateInfo(classNo, className, maintainedContent, maintainedInterval, maintainedPrincipal, facilityId, description);

            this._unitOfWork.RegisterSave(maintainClass);
            this._unitOfWork.Commit();
        }
        #endregion

        #region # 删除设备维护类 —— void RemoveEquipmentMaintainClass(Guid equipmentMaintainClassId)
        /// <summary>
        /// 删除设备维护类
        /// </summary>
        /// <param name="equipmentMaintainClassId">设备维护类Id</param>
        public void RemoveEquipmentMaintainClass(Guid equipmentMaintainClassId)
        {
            this._unitOfWork.RegisterRemove<EquipmentMaintainClass>(equipmentMaintainClassId);
            this._unitOfWork.Commit();
        }
        #endregion

        #region # 创建设备维护记录 —— void CreateEquipmentMaintenance(string maintenanceNo...
        /// <summary>
        /// 创建设备维护记录
        /// </summary>
        /// <param name="maintenanceNo">维护记录编号</param>
        /// <param name="equipmentMaintainClassId">设备维护类Id</param>
        /// <param name="equipmentAssetId">设备资产Id</param>
        /// <param name="maintainedDate">维护日期</param>
        /// <param name="maintainedHour">维护工时</param>
        /// <param name="maintainedParts">维护部位</param>
        /// <param name="maintainedContent">维护内容</param>
        /// <param name="sparePartsUse">备件使用</param>
        /// <param name="maintainer">维护人</param>
        /// <param name="facilityId">工厂模型Id</param>
        /// <param name="description">描述</param>
        public void CreateEquipmentMaintenance(string maintenanceNo, Guid equipmentMaintainClassId, Guid equipmentAssetId, DateTime maintainedDate, decimal? maintainedHour, string maintainedParts, string maintainedContent, string sparePartsUse, string maintainer, Guid? facilityId, string description)
        {
            EquipmentAsset equipmentAsset = this._repMediator.EquipmentAssetRep.Single(equipmentAssetId);
            EquipmentMaintainClass maintainClass = this._repMediator.EquipmentMaintainClassRep.Single(equipmentMaintainClassId);

            EquipmentMaintenance equipmentMaintenance = new EquipmentMaintenance(maintenanceNo, maintainClass.Name, equipmentMaintainClassId, equipmentAsset.EquipmentId, equipmentAssetId, maintainedDate, maintainedHour, maintainedParts, maintainedContent, sparePartsUse, maintainer, facilityId, description);

            this._unitOfWork.RegisterAdd(equipmentMaintenance);
            this._unitOfWork.Commit();
        }
        #endregion

        #region # 修改设备维护记录 —— void UpdateEquipmentMaintenance(Guid equipmentMaintenanceId...
        /// <summary>
        /// 修改设备维护记录
        /// </summary>
        /// <param name="equipmentMaintenanceId">设备维护记录Id</param>
        /// <param name="maintainedDate">维护日期</param>
        /// <param name="maintainedHour">维护工时</param>
        /// <param name="maintainedParts">维护部位</param>
        /// <param name="maintainedContent">维护内容</param>
        /// <param name="sparePartsUse">备件使用</param>
        /// <param name="maintainer">维护人</param>
        /// <param name="facilityId">工厂模型Id</param>
        /// <param name="description">描述</param>
        public void UpdateEquipmentMaintenance(Guid equipmentMaintenanceId, DateTime maintainedDate, decimal? maintainedHour, string maintainedParts, string maintainedContent, string sparePartsUse, string maintainer, Guid? facilityId, string description)
        {
            EquipmentMaintenance equipmentMaintenance = this._unitOfWork.Resolve<EquipmentMaintenance>(equipmentMaintenanceId);
            equipmentMaintenance.UpdateInfo(maintainedDate, maintainedHour, maintainedParts, maintainedContent, sparePartsUse, maintainer, facilityId, description);

            this._unitOfWork.RegisterSave(equipmentMaintenance);
            this._unitOfWork.Commit();
        }
        #endregion

        #region # 删除设备维护记录 —— void RemoveEquipmentMaintenance(Guid equipmentMaintenanceId)
        /// <summary>
        /// 删除设备维护记录
        /// </summary>
        /// <param name="equipmentMaintenanceId">设备维护记录Id</param>
        public void RemoveEquipmentMaintenance(Guid equipmentMaintenanceId)
        {
            this._unitOfWork.RegisterRemove<EquipmentMaintenance>(equipmentMaintenanceId);
            this._unitOfWork.Commit();
        }
        #endregion


        //查询部分

        #region # 分页获取设备资产列表 —— PageModel<EquipmentAssetInfo> GetEquipmentAssetsByPage(string keywords...
        /// <summary>
        /// 分页获取设备资产列表
        /// </summary>
        /// <param name="keywords">关键字</param>
        /// <param name="equipmentId">设备Id</param>
        /// <param name="status">设备状态</param>
        /// <param name="facilityId">工厂模型Id</param>
        /// <param name="pageIndex">页码</param>
        /// <param name="pageSize">页容量</param>
        /// <returns>设备资产列表</returns>
        public PageModel<EquipmentAssetInfo> GetEquipmentAssetsByPage(string keywords, Guid? equipmentId, EquipmentStatus? status, Guid? facilityId, int pageIndex, int pageSize)
        {
            Facility facility = facilityId.HasValue
                ? this._repMediator.FacilityRep.SingleFully(facilityId.Value)
                : null;
            IList<Guid> relatedFacilityIds = facility?.GetDeepNodeIds();

            ICollection<EquipmentAsset> equipmentAssets = this._repMediator.EquipmentAssetRep.FindByPage(keywords, equipmentId, status, relatedFacilityIds, pageIndex, pageSize, out int rowCount, out int pageCount);

            IEnumerable<Guid> equipmentIds = equipmentAssets.Select(x => x.EquipmentId);
            IEnumerable<Guid> facilityIds = equipmentAssets.Where(x => x.FacilityId.HasValue).Select(x => x.FacilityId.Value);
            IDictionary<Guid, EquipmentInfo> equipmentInfos = this._repMediator.EquipmentRep.Find(equipmentIds).ToDictionary(x => x.Key, x => x.Value.ToDTO(null));
            IDictionary<Guid, FacilityInfo> facilityInfos = this._repMediator.FacilityRep.Find(facilityIds).ToDictionary(x => x.Key, x => x.Value.ToDTO());

            IEnumerable<EquipmentAssetInfo> equipmentAssetInfos = equipmentAssets.Select(x => x.ToDTO(equipmentInfos, facilityInfos));

            return new PageModel<EquipmentAssetInfo>(equipmentAssetInfos, pageIndex, pageSize, pageCount, rowCount);
        }
        #endregion

        #region # 分页获取设备维护类列表 —— PageModel<EquipmentMaintainClassInfo> GetEquipmentMaintainClassesByPage(...
        /// <summary>
        /// 分页获取设备维护类列表
        /// </summary>
        /// <param name="keywords">关键字</param>
        /// <param name="facilityId">工厂模型Id</param>
        /// <param name="pageIndex">页码</param>
        /// <param name="pageSize">页容量</param>
        /// <returns>设备维护类列表</returns>
        public PageModel<EquipmentMaintainClassInfo> GetEquipmentMaintainClassesByPage(string keywords, Guid? facilityId, int pageIndex, int pageSize)
        {
            Facility facility = facilityId.HasValue
                ? this._repMediator.FacilityRep.SingleFully(facilityId.Value)
                : null;
            IList<Guid> relatedFacilityIds = facility?.GetDeepNodeIds();

            ICollection<EquipmentMaintainClass> maintainClasses = this._repMediator.EquipmentMaintainClassRep.FindByPage(keywords, relatedFacilityIds, pageIndex, pageSize, out int rowCount, out int pageCount);

            IEnumerable<Guid> facilityIds = maintainClasses.Where(x => x.FacilityId.HasValue).Select(x => x.FacilityId.Value);
            IDictionary<Guid, FacilityInfo> facilityInfos = this._repMediator.FacilityRep.Find(facilityIds).ToDictionary(x => x.Key, x => x.Value.ToDTO());

            IEnumerable<EquipmentMaintainClassInfo> maintainClassInfos = maintainClasses.Select(x => x.ToDTO(facilityInfos));

            return new PageModel<EquipmentMaintainClassInfo>(maintainClassInfos, pageIndex, pageSize, pageCount, rowCount);
        }
        #endregion

        #region # 分页获取设备维护记录列表 —— PageModel<EquipmentMaintenanceInfo> GetEquipmentMaintenancesByPage(...
        /// <summary>
        /// 分页获取设备维护记录列表
        /// </summary>
        /// <param name="keywords">关键字</param>
        /// <param name="equipmentMaintainClassId">设备维护类Id</param>
        /// <param name="equipmentId">设备Id</param>
        /// <param name="equipmentAssetId">设备资产Id</param>
        /// <param name="startTime">开始时间</param>
        /// <param name="endTime">结束时间</param>
        /// <param name="facilityId">工厂模型Id</param>
        /// <param name="pageIndex">页码</param>
        /// <param name="pageSize">页容量</param>
        /// <returns>设备维护记录列表</returns>
        public PageModel<EquipmentMaintenanceInfo> GetEquipmentMaintenancesByPage(string keywords, Guid? equipmentMaintainClassId, Guid? equipmentId, Guid? equipmentAssetId, DateTime? startTime, DateTime? endTime, Guid? facilityId, int pageIndex, int pageSize)
        {
            Facility facility = facilityId.HasValue
                ? this._repMediator.FacilityRep.SingleFully(facilityId.Value)
                : null;
            IList<Guid> relatedFacilityIds = facility?.GetDeepNodeIds();

            ICollection<EquipmentMaintenance> equipmentMaintenances = this._repMediator.EquipmentMaintenanceRep.FindByPage(keywords, equipmentMaintainClassId, equipmentId, equipmentAssetId, startTime, endTime, relatedFacilityIds, pageIndex, pageSize, out int rowCount, out int pageCount);

            IEnumerable<Guid> equipmentMaintainClassIds = equipmentMaintenances.Select(x => x.EquipmentMaintainClassId);
            IEnumerable<Guid> equipmentAssetIds = equipmentMaintenances.Select(x => x.EquipmentAssetId);
            IEnumerable<Guid> facilityIds = equipmentMaintenances.Where(x => x.FacilityId.HasValue).Select(x => x.FacilityId.Value);
            IDictionary<Guid, EquipmentMaintainClassInfo> equipmentMaintainClassInfos = this._repMediator.EquipmentMaintainClassRep.Find(equipmentMaintainClassIds).ToDictionary(x => x.Key, x => x.Value.ToDTO(null));
            IDictionary<Guid, EquipmentAssetInfo> equipmentAssetInfos = this._repMediator.EquipmentAssetRep.Find(equipmentAssetIds).ToDictionary(x => x.Key, x => x.Value.ToDTO(null, null));
            IDictionary<Guid, FacilityInfo> facilityInfos = this._repMediator.FacilityRep.Find(facilityIds).ToDictionary(x => x.Key, x => x.Value.ToDTO());

            IEnumerable<EquipmentMaintenanceInfo> equipmentMaintenanceInfos = equipmentMaintenances.Select(x => x.ToDTO(equipmentMaintainClassInfos, equipmentAssetInfos, facilityInfos));

            return new PageModel<EquipmentMaintenanceInfo>(equipmentMaintenanceInfos, pageIndex, pageSize, pageCount, rowCount);
        }
        #endregion
    }
}
